import { echarts } from '@/utils'
import {
  onUnmounted,
  watch,
  ref,
  markRaw,
  isReactive,
  isRef,
  nextTick
} from 'vue'

/**
 * 为给定的DOM元素和选项初始化并返回一个echarts实例。
 *
 * @param {Ref<HTMLElement>} dom - 要附加echarts实例的DOM元素引用。
 * @param {Object} option - echarts选项对象。
 * @return {Object} chartInstance,setOption, addEvent,removeEvent
 */
export const useEcharts = (dom, option) => {
  let chartInstance = ref(null)

  const resize = () => {
    if (chartInstance.value) {
      chartInstance.value.resize()
    }
  }

  const initChart = () => {
    if (!chartInstance.value && dom.value) {
      chartInstance.value = markRaw(echarts.init(dom.value))
      chartInstance.value.setOption({ ...option })
      window.addEventListener('resize', resize)
    } else if (chartInstance.value) {
      chartInstance.value.resize() // 调整大小而不是重新初始化
    }
  }
  watch(dom, newDom => {
    if (newDom) {
      initChart()
    }
  })

  onUnmounted(() => {
    window.removeEventListener('resize', resize)
    if (chartInstance.value) {
      chartInstance.value.dispose()
    }
  })
  async function setOption(option) {
    await nextTick()
    if (chartInstance.value) {
      chartInstance.value.setOption(option)
    }
  }
  async function dispatchAction(option) {
    await nextTick()
    if (chartInstance.value) {
      chartInstance.value.dispatchAction(option)
    }
  }

  async function addEvent(eventName, handler) {
    await nextTick()
    if (chartInstance.value) {
      chartInstance.value.off(eventName) // 先移除已存在的监听器
      chartInstance.value.on(eventName, handler)
    }
  }

  function removeEvent(eventName, handler) {
    if (chartInstance.value) {
      chartInstance.value.off(eventName, handler)
    }
  }

  async function showLoading(type = 'default', option) {
    await nextTick()
    const loadingOption = {
      text: '' // 提示文本
    }
    if (chartInstance.value) {
      chartInstance.value.showLoading(type, !option && loadingOption)
    }
  }

  async function hideLoading() {
    await nextTick()
    if (chartInstance.value) {
      chartInstance.value.hideLoading()
    }
  }

  // 如果option是响应式的直接更新图表
  if (isReactive(option) || isRef(option)) {
    watch(
      option,
      async newOption => {
        if (chartInstance.value) {
          chartInstance.value.clear()
          if (isRef(option)) {
            setOption({ ...newOption.value })
            return
          }
          setOption({ ...newOption })
        }
      },
      { deep: true }
    )
  }

  return {
    chartInstance,
    setOption,
    addEvent,
    removeEvent,
    dispatchAction,
    showLoading,
    hideLoading
  }
}
